/****************************************************************************
**
** SkillGroupManager.cpp
**
** Copyright (C) August 2014 Hotride
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
*****************************************************************************
*/
//----------------------------------------------------------------------------
#include "stdafx.h"
//----------------------------------------------------------------------------
//----------------------------TSkillGroupObject-------------------------------
//----------------------------------------------------------------------------
TSkillGroupObject::TSkillGroupObject()
: m_Count(0), m_Maximized(false), m_Selected(0), m_Next(NULL), m_Prev(NULL)
{
	memset(m_Items, 0xFF, sizeof(m_Items));
	m_Name = "No Name";
	m_Texture.Width = 0;
	m_Texture.Height = 0;
}
//----------------------------------------------------------------------------
TSkillGroupObject::~TSkillGroupObject()
{
	if (m_Texture.Width) m_Texture.Clear();
}
//----------------------------------------------------------------------------
void TSkillGroupObject::SetName(string val)
{
	m_Name = val;

	if (val.length())
	{
		if (!m_Texture.Empty()) m_Texture.Clear();
		UO->m_Font->GenerateA(6, m_Texture, m_Name.c_str(), 0);
	}
	else if (!m_Texture.Empty()) m_Texture.Clear();
}
//----------------------------------------------------------------------------
BYTE TSkillGroupObject::GetItem(int index)
{
	if (index < 0 || index >= m_Count) return 0xFF;
	return m_Items[index];
}
//----------------------------------------------------------------------------
void TSkillGroupObject::Add(BYTE index)
{
	if (Contains(index)) return;

	m_Items[m_Count] = index;
	m_Count++;
}
//----------------------------------------------------------------------------
void TSkillGroupObject::AddSorted(BYTE index)
{
	if (Contains(index)) return;

	m_Items[m_Count] = index;
	m_Count++;

	Sort();
}
//----------------------------------------------------------------------------
void TSkillGroupObject::Remove(BYTE index)
{
	bool removed = false;

	IFOR(i, 0, m_Count)
	{
		if (m_Items[i] == index)
		{
			removed = true;

			for(; i < m_Count - 1; i++)
			{
				m_Items[i] = m_Items[i + 1];
			}

			break;
		}
	}

	if (removed)
	{
		m_Count--;
		if (m_Count < 0) m_Count = 0;

		m_Items[m_Count] = 0xFF;
	}
}
//----------------------------------------------------------------------------
bool TSkillGroupObject::Contains(BYTE index)
{
	IFOR(i, 0, m_Count)
	{
		if (m_Items[i] == index) return true;
	}

	return false;
}
//----------------------------------------------------------------------------
void TSkillGroupObject::Sort()
{
	BYTE table[60] = {0};
	int Ptr = 0;

	IFOR(i, 0, UO->m_SkillsCount)
	{
		IFOR(j, 0, m_Count)
		{
			if (UO->m_SkillSort.m_Skills[i] == m_Items[j])
			{
				table[Ptr] = m_Items[j];
				Ptr++;
				break;
			}
		}
	}
	
	IFOR(j, 0, m_Count)
	{
		m_Items[j] = table[j];
	}
}
//----------------------------------------------------------------------------
void TSkillGroupObject::TransferTo(TSkillGroupObject *group)
{
	IFOR(i, 0, m_Count)
	{
		group->Add(m_Items[i]);
	}

	group->Sort();
}
//----------------------------------------------------------------------------
//---------------------------TSkillGroupManager------------------------------
//----------------------------------------------------------------------------
TSkillGroupManager::TSkillGroupManager()
: m_Count(0)
{
}
//----------------------------------------------------------------------------
TSkillGroupManager::~TSkillGroupManager()
{
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefault()
{
	Clear();

	MakeDefaultMiscellaneous();
	MakeDefaultCombat();
	MakeDefaultTradeSkills();
	MakeDefaultMagic();
	MakeDefaultWilderness();
	MakeDefaultThieving();
	MakeDefaultBard();

	TSkillGroupObject *group = m_Groups;

	while (group != NULL)
	{
		group->Sort();

		group = group->m_Next;
	}
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultMiscellaneous()
{
	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Miscellaneous");
	group->Add(4);
	group->Add(6);
	group->Add(10);
	group->Add(12);
	group->Add(19);
	group->Add(3);
	group->Add(36);

	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultCombat()
{
	int cnt = UO->m_SkillsCount;

	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Combat");
	group->Add(1);
	group->Add(31);
	group->Add(42);
	group->Add(17);
	group->Add(41);
	group->Add(5);
	group->Add(40);
	group->Add(27);

	if (cnt > 57) group->Add(57); //Throving
	group->Add(43);
	
	if (cnt > 50) group->Add(50); //Focus
	if (cnt > 51) group->Add(51); //Chivalry
	if (cnt > 52) group->Add(52); //Bushido
	if (cnt > 53) group->Add(53); //Ninjitsu

	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultTradeSkills()
{
	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Trade Skills");
	group->Add(0);
	group->Add(7);
	group->Add(8);
	group->Add(11);
	group->Add(13);
	group->Add(23);
	group->Add(44);
	group->Add(45);
	group->Add(34);
	group->Add(37);

	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultMagic()
{
	int cnt = UO->m_SkillsCount;

	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Magic");
	group->Add(16);
	if (cnt > 56) group->Add(56); //Imbuing
	group->Add(25);
	group->Add(46);
	if (cnt > 55) group->Add(55); //Mysticism
	group->Add(26);
	if (cnt > 54) group->Add(54); //Spellweaving
	group->Add(32);
	if (cnt > 49) group->Add(49); //Necromancy
	
	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultWilderness()
{
	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Wilderness");
	group->Add(2);
	group->Add(35);
	group->Add(18);
	group->Add(20);
	group->Add(38);
	group->Add(39);
	
	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultThieving()
{
	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Thieving");
	group->Add(14);
	group->Add(21);
	group->Add(24);
	group->Add(30);
	group->Add(48);
	group->Add(28);
	group->Add(33);
	group->Add(47);
	
	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::MakeDefaultBard()
{
	TSkillGroupObject *group = new TSkillGroupObject();
	group->SetName("Bard");
	group->Add(15);
	group->Add(29);
	group->Add(9);
	group->Add(22);
	
	Add(group);
}
//----------------------------------------------------------------------------
void TSkillGroupManager::Clear()
{
	TSkillGroupObject *item = m_Groups;

	while (item != NULL)
	{
		TSkillGroupObject *next = item->m_Next;

		delete item;

		item = next;
	}

	m_Count = 0;
	m_Groups = NULL;
}
//----------------------------------------------------------------------------
void TSkillGroupManager::Add(TSkillGroupObject *group)
{
	if (m_Groups == NULL)
	{
		m_Groups = group;
		m_Groups->m_Next = NULL;
		m_Groups->m_Prev = NULL;
		m_Count = 1;

		return;
	}

	TSkillGroupObject *item = m_Groups;

	while (item->m_Next != NULL) item = item->m_Next;

	item->m_Next = group;
	group->m_Next = NULL;
	group->m_Prev = item;

	m_Count++;
}
//----------------------------------------------------------------------------
void TSkillGroupManager::Remove(TSkillGroupObject *group)
{
	if (group->m_Prev == NULL) //Miscellaneous
	{
		TGump *gump = new TGump();
		gump->SetType(GT_NOTIFY);
		gump->SetX(UO->m_ConfigManager.GetGameWindowPosX() + (UO->m_ConfigManager.GetGameWindowSizeX() / 2) - 100);
		gump->SetY(UO->m_ConfigManager.GetGameWindowPosY() + (UO->m_ConfigManager.GetGameWindowSizeY() / 2) - 62);
		gump->SetMiniX(200);
		gump->SetMiniY(125);
		gump->SetName("Cannot delete this group.");
		gump->SetPage(2);

		g_GrayMenuCount++;

		UO->AddGump(gump);

		UO->InitGump(GS_GAME_BLOCKED);
		UO->SetBlockedGumpCode(4);
		return;
	}

	m_Count--;
	if (m_Count < 0) m_Count = 0;

	if (group->m_Next != NULL) group->m_Next->m_Prev = group->m_Prev;
		group->m_Prev->m_Next = group->m_Next;

	group->TransferTo(m_Groups);
	delete group;
}
//----------------------------------------------------------------------------
int TSkillGroupManager::GetVisibleLinesCount()
{
	int count = 0;

	TSkillGroupObject *group = m_Groups;
	while (group != NULL)
	{
		count++;
		if (group->GetMaximized()) count += group->GetCount();

		group = group->m_Next;
	}

	if (count) count--;

	return count;
}
//----------------------------------------------------------------------------
int TSkillGroupManager::Load(FILE *file)
{
	Clear();

	int readbytes = 0;

	WORD w = 0;
	readbytes += (int)fread(&w, 1, 2, file);
	int Count = w;

	IFOR(i, 0, Count)
	{
		TSkillGroupObject *group = new TSkillGroupObject();
		readbytes += (int)fread(&w, 1, 2, file);

		char name[64] = {0};
		readbytes += (int)fread(name, 1, w, file);
		group->SetName(name);

		readbytes += (int)fread(&w, 1, 2, file);

		IFOR(j, 0, w)
		{
			BYTE b = 0xFF;
			readbytes += (int)fread(&b, 1, 1, file);
			if (b != 0xFF) group->Add(b);
		}

		group->Sort();

		Add(group);
	}

	return readbytes;
}
//----------------------------------------------------------------------------
void TSkillGroupManager::Save(FILE *file)
{
	WORD w = (WORD)m_Count;
	fwrite(&w, 2, 1, file);

	m_Count = 0;
	TSkillGroupObject *group = m_Groups;
	while (group != NULL)
	{
		m_Count++;
		group = group->m_Next;
	}

	group = m_Groups;
	IFOR(i, 0, m_Count)
	{
		w = (WORD)group->GetName().length() + 1;
		fwrite(&w, 2, 1, file);

		char name[64] = {0};
		sprintf(name, "%s", group->GetName().c_str());
		name[w - 1] = 0;
		fwrite(name, w, 1, file);

		w = (WORD)group->GetCount();
		fwrite(&w, 2, 1, file);

		IFOR(j, 0, w)
		{
			BYTE b = group->GetItem(j);
			fwrite(&b, 1, 1, file);
		}

		group = group->m_Next;
	}
}
//----------------------------------------------------------------------------